Como siempre, lo primero que debemos hacer es importar las librerĆas necesarias:
# LibrerĆa para manejo de tensores
import tensorflow as tf
# API para AI sobre motor de tensores
from tensorflow import keras
# Manejo de arreglos
import numpy as np
# Dibujitos
import matplotlib.pyplot as plt
En esta ocasión y por ser la introducción, mostraremos que el proceso de optimización visto en clase (usando JAX), es equivalente a construir una red neuronal artificial.
Para esto, simulemos unos datos de prueba:
# Genera datos espaciados uniformemente
x=np.linspace(-10,10,50)
# Modelo generado a partir de las entradas
y=2*x**2+3*x+5*np.random.normal(0,4,size=len(x))
Observemos algo de los datos simulados:
print(x)
[-10. -9.59183673 -9.18367347 -8.7755102 -8.36734694 -7.95918367 -7.55102041 -7.14285714 -6.73469388 -6.32653061 -5.91836735 -5.51020408 -5.10204082 -4.69387755 -4.28571429 -3.87755102 -3.46938776 -3.06122449 -2.65306122 -2.24489796 -1.83673469 -1.42857143 -1.02040816 -0.6122449 -0.20408163 0.20408163 0.6122449 1.02040816 1.42857143 1.83673469 2.24489796 2.65306122 3.06122449 3.46938776 3.87755102 4.28571429 4.69387755 5.10204082 5.51020408 5.91836735 6.32653061 6.73469388 7.14285714 7.55102041 7.95918367 8.36734694 8.7755102 9.18367347 9.59183673 10. ]
print(y)
[164.51293268 125.06310909 126.09615855 172.6455916 82.48431536 110.64634991 96.13407121 88.33052181 48.15878265 69.74792564 40.75117108 41.59893563 27.89987563 53.60668475 50.8516986 -30.1562971 17.51811256 48.74021386 5.30598157 4.54312822 7.29011522 -14.50833753 33.65527705 -2.61214908 -29.67285518 -22.37158368 28.71740286 23.09563483 28.92067908 -4.19299509 23.47884775 20.01359748 18.03393006 7.01915421 54.87707004 28.83370182 76.93860316 71.32705485 41.29499325 83.07673062 87.14710317 94.02270753 132.22015773 112.90137633 148.51421124 147.41479907 199.07091548 171.87390047 204.41336392 255.16672667]
En lo posible, trate de visualizar datos para tener una intuición sobre lo que estÔ pasando. Es claro que no siempre es posible hacerlo, pero exsiten, por ejemplo, técnicas de reducción de dimensión para dar una idea vaga de lo que estÔ pasando.
# Generar Lienzo
plt.figure(figsize=(15,7))
#Titulo del lienzo
plt.title("Visualización de Datos",fontsize=15)
#Dibujar datos
plt.plot(x,y,'o')
# Leyenda de los datos
plt.legend(["Datos"],fontsize=15)
# Nombrar Ejes
plt.xlabel("$Tiempo$",fontsize=15)
plt.ylabel("$Valor$",fontsize=15)
# Poner cuadrĆcula
plt.grid()
# Mostrar imagen
plt.show()
Para construir nuestra primera red Neuronal, recuerde el siguiente dibujo:

Vemos que el dibujo opera de izquierda a derecha ($\rightarrow$), por lo que tiene sentido llamarlo Modelo Secuencial.
En este caso, usaremos una neurona (units) y la dimensión de entrada es unidimensional (input_shape)
model = keras.Sequential(
keras.layers.Dense(units=1,input_shape=(1,))
)
Ahora que tenemos nuestra maqueta de las ecuaciones del modelo, elegimos una función de pérdida adecuada a nuestro problema y un optimizador para minimizar dicha pérdida:
model.compile(optimizer='sgd', loss='mean_squared_error')
El modelo creado y compilado tiene muchos otros mƩtodos interesantes.
Por ejemplo, podemos ver el resumen de lo que tiene la red.
model.summary()
Model: "sequential_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_1 (Dense) (None, 1) 2 ================================================================= Total params: 2 Trainable params: 2 Non-trainable params: 0 _________________________________________________________________
También es posible visualizar los modelos en forma de grafo, lo cual es muy útil para tener control global de la arquitectura del modelo:
from tensorflow.keras.utils import plot_model
plot_model(model,show_shapes=True)
#Obtener Pesos de la Red
w=model.get_weights();
print(w)
#Imprimir resultados
print("\nObjeto Pesos:",w)
print('\nNumber of Weights -> '+ str(len(w)))
print('\nw = ' + str(w[0][0]) +'(Weight)')
print('b = ' + str(w[1])+'("Weight"->Bias)')
[array([[4.415526]], dtype=float32), array([38.15945], dtype=float32)]
Objeto Pesos: [array([[4.415526]], dtype=float32), array([38.15945], dtype=float32)]
Number of Weights -> 2
w = [4.415526](Weight)
b = [38.15945]("Weight"->Bias)
predecir=model.predict(x)
#print(predecir)
#np.vstack((predecir.reshape(-1,),y)).T
plt.figure(figsize=(15,7))
plt.plot(x,predecir,'r-',label='Model: y={:.2f}*x+{:.2f}'.format(w[0].item(),w[1].item()))
plt.plot(x,y,'o', label='Data')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
model2 = tf.keras.Sequential([
keras.layers.Dense(units=5,input_shape=(1,),activation='softplus'),
keras.layers.Dense(units=10,activation='softplus'),
keras.layers.Dense(units=20,activation='softplus'),
keras.layers.Dense(units=1),
])
model2.compile(optimizer='adam', loss='mean_squared_error')
model2.summary()
history=model2.fit(x, y, epochs=1000,verbose=0)
#Obtener Pesos de la Red
w2=model2.get_weights();
#Imprimir resultados
#print("\nObjeto Pesos:",w2)
#print('\nNumber of Weights -> '+ str(len(w2)))
#print('\nw = ' + str(w[0][0]) +'(Weight)')
#print('b = ' + str(w[1])+'("Weight"->Bias)')
x_test=np.linspace(x[0],x[-1],300)
predecir=model2.predict(x_test)
plt.figure(figsize=(15,8))
plt.plot(x_test,predecir,label='Model')
plt.plot(x,y,'o', label='Data')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
plt.figure(figsize=(15,8))
plt.plot(history.history['loss'],'r-',label='Loss')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
trend=0.1
time=np.arange(0,100,0.1)
y=trend*time+np.sin(time)+np.random.normal(scale=0.5,size=len(time))
plt.figure(figsize=(15,8))
plt.title("Visualización de Datos",fontsize=15)
plt.plot(time,y,'-')
plt.legend(["Datos"],fontsize=15)
plt.xlabel("$x$",fontsize=15)
plt.ylabel("$y$",fontsize=15)
plt.grid()
plt.show()
model3 = tf.keras.Sequential([
keras.layers.Dense(units=10,input_shape=(1,),activation='elu'),
keras.layers.Dense(units=20,activation='elu'),
keras.layers.Dense(units=30,activation='elu'),
keras.layers.Dense(units=40,activation='elu'),
keras.layers.Dense(units=50,activation='elu'),
keras.layers.Dense(units=60,activation='elu'),
keras.layers.Dense(units=70,activation='elu'),
keras.layers.Dense(units=1)
])
model3.compile(optimizer='adam', loss='mean_squared_error')
model3.summary()
Model: "sequential_2" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= dense_5 (Dense) (None, 10) 20 _________________________________________________________________ dense_6 (Dense) (None, 20) 220 _________________________________________________________________ dense_7 (Dense) (None, 30) 630 _________________________________________________________________ dense_8 (Dense) (None, 40) 1240 _________________________________________________________________ dense_9 (Dense) (None, 50) 2050 _________________________________________________________________ dense_10 (Dense) (None, 60) 3060 _________________________________________________________________ dense_11 (Dense) (None, 70) 4270 _________________________________________________________________ dense_12 (Dense) (None, 1) 71 ================================================================= Total params: 11,561 Trainable params: 11,561 Non-trainable params: 0 _________________________________________________________________
history=model3.fit(time, y, epochs=10000,verbose=0)
#Obtener Pesos de la Red
w3=model3.get_weights();
#Imprimir resultados
#print("\nObjeto Pesos:",w2)
#print('\nNumber of Weights -> '+ str(len(w2)))
#print('\nw = ' + str(w[0][0]) +'(Weight)')
#print('b = ' + str(w[1])+'("Weight"->Bias)')
x_test=np.linspace(time[0],time[-1],3000)
predecir=model3.predict(x_test)
plt.figure(figsize=(15,8))
plt.plot(time,y,'-', label='Data')
plt.plot(x_test,predecir,'r',label='Model')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
plt.figure(figsize=(15,8))
plt.plot(history.history['loss'],'r-',label='Model')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from tensorflow import keras
from tensorflow.keras.layers import Activation, Input,Dense
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
trend=0.1
time=np.arange(0,100,0.1)
y=trend*time+np.sin(time)+np.random.normal(scale=0.5,size=len(time))
inputs=Input(shape=(1,))
output=inputs
capas=10
dim=10
output=Activation('elu')(output)
for capa in range(capas):
output=Dense(dim)(output)
output=Activation('elu')(output)
dim+=10
output=Dense(1)(output)
model=Model(inputs,output)
model.compile(loss='mse',optimizer='adam')
model.summary()
Model: "functional_1" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= input_1 (InputLayer) [(None, 1)] 0 _________________________________________________________________ activation (Activation) (None, 1) 0 _________________________________________________________________ dense_13 (Dense) (None, 10) 20 _________________________________________________________________ activation_1 (Activation) (None, 10) 0 _________________________________________________________________ dense_14 (Dense) (None, 20) 220 _________________________________________________________________ activation_2 (Activation) (None, 20) 0 _________________________________________________________________ dense_15 (Dense) (None, 30) 630 _________________________________________________________________ activation_3 (Activation) (None, 30) 0 _________________________________________________________________ dense_16 (Dense) (None, 40) 1240 _________________________________________________________________ activation_4 (Activation) (None, 40) 0 _________________________________________________________________ dense_17 (Dense) (None, 50) 2050 _________________________________________________________________ activation_5 (Activation) (None, 50) 0 _________________________________________________________________ dense_18 (Dense) (None, 60) 3060 _________________________________________________________________ activation_6 (Activation) (None, 60) 0 _________________________________________________________________ dense_19 (Dense) (None, 70) 4270 _________________________________________________________________ activation_7 (Activation) (None, 70) 0 _________________________________________________________________ dense_20 (Dense) (None, 80) 5680 _________________________________________________________________ activation_8 (Activation) (None, 80) 0 _________________________________________________________________ dense_21 (Dense) (None, 90) 7290 _________________________________________________________________ activation_9 (Activation) (None, 90) 0 _________________________________________________________________ dense_22 (Dense) (None, 100) 9100 _________________________________________________________________ activation_10 (Activation) (None, 100) 0 _________________________________________________________________ dense_23 (Dense) (None, 1) 101 ================================================================= Total params: 33,661 Trainable params: 33,661 Non-trainable params: 0 _________________________________________________________________
history=model.fit(time,y,epochs=500,verbose=0)
x_test=np.linspace(time[0],time[-1],1000)
predecir=model.predict(x_test)
plt.figure(figsize=(15,8))
plt.plot(time[0:300],y[0:300],'-', label='Data')
plt.plot(x_test[0:300],predecir[0:300],'r',label='Model')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
plt.figure(figsize=(15,8))
plt.plot(history.history['loss'],'r-',label='Model')
plt.title('Plotting Model vs Data')
plt.legend(loc=0)
plt.show()
Construyamos una red convolucional para ver el beneficio sobre una red densa.
Para este proceso, realicemos nuestra rutina de cargar los datos, observar unos cuantos ejemplos y comprobar unas cuantas estadĆsticas:
# apunta los datos
mnist = tf.keras.datasets.mnist
# lee los conjuntos de datos, los cuales vienen separados de antemano para entrenamiento y test
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
# Verificar forma de los datos
print("Forma de los datos:",training_images.shape)
Forma de los datos: (60000, 28, 28)
# reshape para colocar los datos de entrenamiento en el fomato apropiado.
# Agrega una dimensión al final y normaliza los datos
training_images=training_images.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
# reshape para colocar los datos de test en el fomato apropiado. Agrega una dimensión al final y normaliza los datos
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images/255.0
print("Nueva forma de los datos:", training_images.shape)
Nueva forma de los datos: (60000, 28, 28, 1)
np.set_printoptions(linewidth=200,precision=2)
Capa 1: Conv2D con 32 filtros (kernels) de tamaño 3*3. Cada image viene en un tensor de tamaño 28 x 28 x 1. Los filtros son pasados por una f. de activación 'relu'.
Capa 2. MaxPooling. Reduce cada filtro. Toma regiones secuenciales 2*2 y los reduce tomando el mÔximo de cada región. No usa f. de activación.
Capa 3. Flatten. Toma todos los filtros resultantes de la capa MaxPooling y los organiza como un Ćŗnico tensor unidimensional
Capa 4. Dense. Recibe el tensor saliente de la capa Flatten y genera una salida en 128 unidades, usando activación relu
Capa 5. Dense. Recibe el tensor unidmensional de tamaƱo 128 y lo transforma en la salida de 10 unidades. Hay 10 clases.
El predictor es al final transformado por la acticación softmax para obtener una distribución de la posible clase para la imagend e entrada
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(filters=32, kernel_size=(3,3), activation='relu', input_shape=(28, 28, 1)),
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
Es de Extremada importancia ver el diseƱo de la red para ver quƩ tantos parƔmetros tiene el modelo:
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
history = model.fit(training_images, training_labels,
epochs=20,
validation_split=0.2,
batch_size=64,
callbacks=[accu_callback])
Epoch 1/20 750/750 [==============================] - 3s 4ms/step - loss: 0.1951 - accuracy: 0.9434 - val_loss: 0.0890 - val_accuracy: 0.9738 Epoch 2/20 750/750 [==============================] - 3s 4ms/step - loss: 0.0628 - accuracy: 0.9816 - val_loss: 0.0608 - val_accuracy: 0.9829 Epoch 3/20 750/750 [==============================] - 3s 4ms/step - loss: 0.0417 - accuracy: 0.9870 - val_loss: 0.0571 - val_accuracy: 0.9826 Epoch 4/20 750/750 [==============================] - ETA: 0s - loss: 0.0284 - accuracy: 0.9911 Se alcanzó un 98.5% de precisión en la validación! Cancelando Entrenamiento... 750/750 [==============================] - 3s 4ms/step - loss: 0.0284 - accuracy: 0.9911 - val_loss: 0.0516 - val_accuracy: 0.9856
Veremos ahora qué tan bien hizo el modelo en su fase de entrenamiento, viendo las grÔficas de entrenamiento tanto en pérdida como en precisión.
import matplotlib.pyplot as plt
# Del objeto history, podemos sacar la información guardada a traveŠdel entrenamiento
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1,len(acc)+1)
n_row = 1
n_col = 2
fig, ax = plt.subplots(n_row, n_col, sharex = False, sharey = False, figsize=(16,4))
ax[0].plot(epochs, acc, 'r', label='Training accuracy')
ax[0].plot(epochs, val_acc, 'b', label='Validation accuracy')
ax[0].legend(fontsize=12,loc=0)
ax[0].set_title('Training and Validation Accuracy',fontsize=16)
ax[0].set_ylabel('measure',fontsize=14)
ax[0].set_xlabel('epoch', fontsize = 14)
ax[0].set_xlim([1, len(acc)])
ax[1].plot(epochs, loss, 'r', label='Training Loss')
ax[1].plot(epochs, val_loss, 'b', label='Validation Loss')
ax[1].legend(fontsize=12)
ax[1].set_title('Training and Validation Loss',fontsize=16)
ax[1].set_ylabel('measure',fontsize=14)
ax[1].set_xlabel('epoch', fontsize = 14)
ax[1].set_xlim([1, len(acc)])
plt.show()
model.evaluate(test_images,test_labels)
313/313 [==============================] - 0s 940us/step - loss: 0.0463 - accuracy: 0.9849
[0.04629792645573616, 0.9848999977111816]
model.save('../Datos/model_MNIST.h5')
#model.save('/tmp/model_MNIST.h5')
Calcula las clases predichas las probabilidades calculadas por softmax
preds = model.predict(test_images)
print(preds.shape)
(10000, 10)
Observemos que las predicciones vienen en forma de probabilidad:
#Elegir un elemento de test al azar
azar_test=np.random.randint(len(test_images))
#mostrar vector de probabilidades (resultado del softmax)
print(np.round(preds[azar_test],2))
[0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
AsĆ pues, elegiremos el indice de la mayor probabilidad para elegir la etiqueta predicha:
# Calcular el Ćndice + mĆ”ximo por filas
label_preds=np.argmax(preds,axis=1)
print("CuƔntos label predichos:",label_preds.shape,'\n')
print("Predicciones:\n")
print(label_preds)
CuƔntos label predichos: (10000,) Predicciones: [7 2 1 ... 4 5 6]
En consecuencia, de nuestro elemento elegido al azar, podemos decir que la predicción es:
print("Etiqueta predicha:",label_preds[azar_test])
Etiqueta predicha: 4
print("MƔquina vs Humano\n")
plt.imshow(test_images[azar_test,:,:,0],cmap='binary')
#plt.axis('off')
plt.title('label humano: ' +str(test_labels[azar_test]),fontsize=14)
plt.xlabel("label mƔquina: "+str(label_preds[azar_test]),fontsize=14)
plt.xticks([], [])
plt.yticks([], [])
plt.show()
MƔquina vs Humano
azar_test= np.random.randint(len(bad_pred))
print("Mala Predicción:\n")
plt.title('Humano: ' +str(test_labels[bad_pred[azar_test]]),fontsize=16)
plt.imshow(test_images[bad_pred[azar_test],:,:,0],cmap='gray')
plt.xlabel("MƔquina: "+str(np.argmax(preds[bad_pred[azar_test]])),fontsize=14)
plt.show()
Mala Predicción:
Hagamos el mismo proceso anterior, pero Ʃsta vez usando el conjunto de prendas MNIST Fashion.
Comenzamos cargando los datos:
# apunta los datos
mnist_fashion = tf.keras.datasets.fashion_mnist
# lee los conjuntos de datos, los cuales vienen separados de antemano para entrenamiento y test
(training_images, training_labels), (test_images, test_labels) = mnist_fashion.load_data()
# Verificar forma de los datos
print("Forma de los datos de entrenamiento:",training_images.shape)
Forma de los datos de entrenamiento: (60000, 28, 28)
# reshape para colocar los datos de entrenamiento en el fomato apropiado.
# Agrega una dimensión al final y normaliza los datos
training_images=training_images.reshape(60000, 28, 28, 1)
training_images=training_images / 255.0
# reshape para colocar los datos de test en el fomato apropiado. Agrega una dimensión al final y normaliza los datos
test_images = test_images.reshape(10000, 28, 28, 1)
test_images=test_images/255.0
print("Nueva forma de los datos de entrenamiento:", training_images.shape)
Nueva forma de los datos de entrenamiento: (60000, 28, 28, 1)
No olvidemos que a pesar de tener etiquetas en forma de nĆŗmero en nuestro conjunto de datos, ellas corresponden a nombres de objetos.
No debemos perder ésta conexión, asà que traemos la lista de nombres por aparte:
nombres_prendas = ['Camiseta/top', 'Pantalón', 'Jersey', 'Vestido', 'Abrigo',
'Sandalia', 'Camisa', 'Tenis', 'Bolso', 'Botines']
# muestra una imagen de entranamiento
azar=np.random.randint(len(training_images))
print("Datos en bruto:\n")
print(training_images[azar,10:15,10:15,0],'\n')
print("Imagen Asociada:\n")
plt.imshow(training_images[azar,:,:,0],cmap='binary')
plt.axis('off')
plt.title(str(nombres_prendas[training_labels[azar]]),fontsize=16)
plt.show()
Datos en bruto: [[0.89019608 0.90196078 0.89411765 0.89803922 0.89803922] [0.89803922 0.90588235 0.90196078 0.89411765 0.89803922] [0.90196078 0.90588235 0.90196078 0.89411765 0.89803922] [0.90588235 0.90196078 0.90196078 0.89803922 0.90980392] [0.90196078 0.90196078 0.90196078 0.90196078 0.90980392]] Imagen Asociada:
#CuƔntas filas
filas=3
#Cuantas columnas
colus=4
#Elementos totales
n=filas*colus
#Elegir una muestra del dataset via Ćndices
vector_azar=np.random.randint(len(training_images),size=(n,))
# contador para dibujar en la grilla
w=1
#iniciar espacio de dibujo
plt.figure(figsize=(15,10))
#titulo
plt.suptitle("Ejemplos del dataset MNIST Fashion",fontsize=18)
# Loop anidado para recorrer la matriz completa
for i in range(filas):
for j in range(colus):
# subplots se peden contar incrementalmente
plt.subplot(filas,colus,w)
# dibujar el ejemplo de la muestra convertida a una matrix 28X28
plt.imshow(training_images[vector_azar[w-1]].reshape((28, 28)), cmap="binary")
#mostrar la etiqueta dada por el humano a dicho ejemplo (Aprendizaje supervisado)
plt.title(nombres_prendas[training_labels[vector_azar[w-1]]],fontsize=16)
#No mostrar ejes corrdenados
plt.axis("off")
# Incrementar contador
w+=1
plt.show()
#mostrar Ćndices de los ejemplos elegidos
print("\nIndices Elegidos: ",vector_azar,"\n")
# mostrar etiquetas correspondientes
print("\nElementos Elegidos: ",training_labels[vector_azar],"\n")
Indices Elegidos: [18907 43759 40151 18870 24053 57054 52309 18663 56167 6379 37429 37985] Elementos Elegidos: [4 8 3 6 4 5 0 5 5 9 7 6]
Capa 1: Conv2D con 64 filtros (kernels) de tamaño 3*3. Cada image viene en un tensor de tamaño 28 x 28 x 1. Los filtros son pasados por una f. de activación 'relu'.
Capa 2. MaxPooling. Reduce cada filtro. Toma regiones secuenciales 2*2 y los reduce tomando el mÔximo de cada región. No usa f. de activación.
Capa 1: Conv2D con 64 filtros (kernels) de tamaño 3*3. Cada image viene en un tensor de tamaño 28 x 28 x 1. Los filtros son pasados por una f. de activación 'relu'.
Capa 2. MaxPooling. Reduce cada filtro. Toma regiones secuenciales 2*2 y los reduce tomando el mÔximo de cada región. No usa f. de activación.
Capa 3. Flatten. Toma todos los filtros resultantes de la capa MaxPooling y los organiza como un Ćŗnico tensor unidimensional
Capa 4. Dense. Recibe el tensor saliente de la capa Flatten y genera una salida en 128 unidades, usando activación relu
Capa 5. Dense. Recibe el tensor unidmensional de tamaƱo 128 y lo transforma en la salida de 10 unidades. Hay 10 clases.
El predictor es al final transformado por la acticación softmax para obtener una distribución de la posible clase para la imagend e entrada
model = tf.keras.models.Sequential([
###Capas convolucionadas
#Convolución 1
tf.keras.layers.Conv2D(filters=64, kernel_size=(3,3), activation='relu', input_shape=(28, 28, 1)),
#Pooling 1
tf.keras.layers.MaxPooling2D(2, 2),
tf.keras.layers.Dropout(0.4),
#Convolución 2
tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
#Pooling 2
tf.keras.layers.MaxPooling2D(2,2),
###Capas Densas
# Aplanamiento
tf.keras.layers.Flatten(),
#Capa Densa
tf.keras.layers.Dropout(0.4),
tf.keras.layers.Dense(128, activation='relu'),
#Capa densa, clasificación
tf.keras.layers.Dense(10, activation='softmax')
])
Es de Extremada importancia ver el diseƱo de la red para ver quƩ tantos parƔmetros tiene el modelo:
model.summary()
Model: "sequential_10"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_20 (Conv2D) (None, 26, 26, 64) 640
max_pooling2d_20 (MaxPoolin (None, 13, 13, 64) 0
g2D)
dropout_6 (Dropout) (None, 13, 13, 64) 0
conv2d_21 (Conv2D) (None, 11, 11, 128) 73856
max_pooling2d_21 (MaxPoolin (None, 5, 5, 128) 0
g2D)
flatten_10 (Flatten) (None, 3200) 0
dropout_7 (Dropout) (None, 3200) 0
dense_20 (Dense) (None, 128) 409728
dense_21 (Dense) (None, 10) 1290
=================================================================
Total params: 485,514
Trainable params: 485,514
Non-trainable params: 0
_________________________________________________________________
Se usa para pasar funciones de control al algoritmo de estimación.
AquĆ la usaremos para el entrenamiento pare cuando se alcance un determinado accuracy con los datos de entrenamiento.
tf.keras.callbacks.Callback es una clase abstracta para permitir escribir mƩtodos que actuan en el proceso de entranamiento o de test. Para detalles vea tf.keras.callbacks.Callback.
class MNIST_Callback(tf.keras.callbacks.Callback):
# mƩtodo dentro de la clase myCallback, heredada de la clase Callback de keras
def on_epoch_end(self, epoch, logs={}):
if(logs.get('val_accuracy')>=0.98):
print("\nSe alcanzó un 99.9% de precisión en el entrenamiento! Cancelando Entrenamiento...")
self.model.stop_training = True
# crea una instancia de clase
accu_callback = MNIST_Callback()
Observen como se pasan los callbacks
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
history = model.fit(training_images, training_labels,
epochs=40,
validation_split=0.2,
batch_size=64,
callbacks=[accu_callback])
Epoch 1/40 750/750 [==============================] - 10s 13ms/step - loss: 0.5633 - accuracy: 0.7922 - val_loss: 0.3809 - val_accuracy: 0.8625 Epoch 2/40 750/750 [==============================] - 10s 13ms/step - loss: 0.3693 - accuracy: 0.8652 - val_loss: 0.3165 - val_accuracy: 0.8855 Epoch 3/40 750/750 [==============================] - 10s 13ms/step - loss: 0.3239 - accuracy: 0.8798 - val_loss: 0.3025 - val_accuracy: 0.8892 Epoch 4/40 750/750 [==============================] - 10s 13ms/step - loss: 0.2977 - accuracy: 0.8907 - val_loss: 0.2790 - val_accuracy: 0.8982 Epoch 5/40 750/750 [==============================] - 10s 13ms/step - loss: 0.2747 - accuracy: 0.8981 - val_loss: 0.2852 - val_accuracy: 0.8923 Epoch 6/40 750/750 [==============================] - 10s 13ms/step - loss: 0.2577 - accuracy: 0.9037 - val_loss: 0.2528 - val_accuracy: 0.9077 Epoch 7/40 750/750 [==============================] - 10s 13ms/step - loss: 0.2469 - accuracy: 0.9068 - val_loss: 0.2477 - val_accuracy: 0.9068 Epoch 8/40 750/750 [==============================] - 10s 13ms/step - loss: 0.2337 - accuracy: 0.9121 - val_loss: 0.2565 - val_accuracy: 0.9043 Epoch 9/40 750/750 [==============================] - 10s 13ms/step - loss: 0.2224 - accuracy: 0.9161 - val_loss: 0.2354 - val_accuracy: 0.9122 Epoch 10/40 750/750 [==============================] - 10s 13ms/step - loss: 0.2139 - accuracy: 0.9188 - val_loss: 0.2447 - val_accuracy: 0.9076 Epoch 11/40 750/750 [==============================] - 10s 13ms/step - loss: 0.2031 - accuracy: 0.9247 - val_loss: 0.2305 - val_accuracy: 0.9132 Epoch 12/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1967 - accuracy: 0.9246 - val_loss: 0.2283 - val_accuracy: 0.9151 Epoch 13/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1875 - accuracy: 0.9279 - val_loss: 0.2251 - val_accuracy: 0.9180 Epoch 14/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1810 - accuracy: 0.9315 - val_loss: 0.2296 - val_accuracy: 0.9157 Epoch 15/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1797 - accuracy: 0.9315 - val_loss: 0.2234 - val_accuracy: 0.9194 Epoch 16/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1723 - accuracy: 0.9334 - val_loss: 0.2301 - val_accuracy: 0.9141 Epoch 17/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1642 - accuracy: 0.9375 - val_loss: 0.2310 - val_accuracy: 0.9153 Epoch 18/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1633 - accuracy: 0.9382 - val_loss: 0.2306 - val_accuracy: 0.9138 Epoch 19/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1567 - accuracy: 0.9403 - val_loss: 0.2546 - val_accuracy: 0.9037 Epoch 20/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1497 - accuracy: 0.9423 - val_loss: 0.2419 - val_accuracy: 0.9162 Epoch 21/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1491 - accuracy: 0.9421 - val_loss: 0.2253 - val_accuracy: 0.9189 Epoch 22/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1466 - accuracy: 0.9431 - val_loss: 0.2425 - val_accuracy: 0.9164 Epoch 23/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1411 - accuracy: 0.9470 - val_loss: 0.2301 - val_accuracy: 0.9200 Epoch 24/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1405 - accuracy: 0.9469 - val_loss: 0.2353 - val_accuracy: 0.9168 Epoch 25/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1367 - accuracy: 0.9483 - val_loss: 0.2411 - val_accuracy: 0.9175 Epoch 26/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1334 - accuracy: 0.9490 - val_loss: 0.2446 - val_accuracy: 0.9182 Epoch 27/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1322 - accuracy: 0.9491 - val_loss: 0.2270 - val_accuracy: 0.9228 Epoch 28/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1252 - accuracy: 0.9518 - val_loss: 0.2465 - val_accuracy: 0.9187 Epoch 29/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1272 - accuracy: 0.9514 - val_loss: 0.2500 - val_accuracy: 0.9163 Epoch 30/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1254 - accuracy: 0.9530 - val_loss: 0.2384 - val_accuracy: 0.9184 Epoch 31/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1222 - accuracy: 0.9534 - val_loss: 0.2401 - val_accuracy: 0.9171 Epoch 32/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1201 - accuracy: 0.9541 - val_loss: 0.2520 - val_accuracy: 0.9153 Epoch 33/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1164 - accuracy: 0.9551 - val_loss: 0.2413 - val_accuracy: 0.9183 Epoch 34/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1178 - accuracy: 0.9554 - val_loss: 0.2522 - val_accuracy: 0.9227 Epoch 35/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1118 - accuracy: 0.9569 - val_loss: 0.2459 - val_accuracy: 0.9186 Epoch 36/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1123 - accuracy: 0.9575 - val_loss: 0.2719 - val_accuracy: 0.9151 Epoch 37/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1127 - accuracy: 0.9579 - val_loss: 0.2580 - val_accuracy: 0.9187 Epoch 38/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1118 - accuracy: 0.9565 - val_loss: 0.2499 - val_accuracy: 0.9207 Epoch 39/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1086 - accuracy: 0.9582 - val_loss: 0.2553 - val_accuracy: 0.9201 Epoch 40/40 750/750 [==============================] - 10s 13ms/step - loss: 0.1082 - accuracy: 0.9600 - val_loss: 0.2522 - val_accuracy: 0.9216
Veremos ahora qué tan bien hizo el modelo en su fase de entrenamiento, viendo las grÔficas de entrenamiento tanto en pérdida como en precisión.
model.evaluate(test_images,test_labels)
313/313 [==============================] - 1s 2ms/step - loss: 0.2701 - accuracy: 0.9185
[0.2700694501399994, 0.9185000061988831]
model.save('../Datos/model_MNIST_Fashion.h5')
import matplotlib.pyplot as plt
# Del objeto history, podemos sacar la información guardada a traveŠdel entrenamiento
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(acc))
n_row = 1
n_col = 2
fig, ax = plt.subplots(n_row, n_col, sharex = False, sharey = False, figsize=(16,4))
ax[0].plot(epochs, acc, 'r', label='Training accuracy')
ax[0].plot(epochs, val_acc, 'b', label='Validation accuracy')
ax[0].legend(fontsize=12,loc=0)
ax[0].set_title('Training and Validation Accuracy',fontsize=16)
ax[0].set_ylabel('measure',fontsize=14)
ax[0].set_xlabel('epoch', fontsize = 14)
ax[0].set_xlim([1, len(acc)])
ax[1].plot(epochs, loss, 'r', label='Training Loss')
ax[1].plot(epochs, val_loss, 'b', label='Validation Loss')
ax[1].legend(fontsize=12)
ax[1].set_title('Training and Validation Loss',fontsize=16)
ax[1].set_ylabel('measure',fontsize=14)
ax[1].set_xlabel('epoch', fontsize = 14)
ax[1].set_xlim([1, len(acc)])
plt.show()
Calcula las clases predichas las probabilidades calculadas por softmax
preds = model.predict(test_images)
print(preds.shape)
(10000, 10)
Observemos que las predicciones vienen en forma de probabilidad:
#Elegir un elemento de test al azar
azar_test=np.random.randint(len(test_images))
#mostrar vecto de probabilidades (resultado del softmax)
print(np.round(preds[azar_test],2))
[0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
AsĆ pues, elegiremos el indice de la mayor probabilidad para elegir la etiqueta predicha:
# Calcular el Ćnidce mĆ”ximo por filas
label_preds=np.argmax(preds,axis=1)
print("Cuantos label predichos:",label_preds.shape,'\n')
print("Predicciones:\n")
print(label_preds)
Cuantos label predichos: (10000,) Predicciones: [9 2 1 ... 8 1 5]
Asà pues, de nuestro elemento elegido al azar, podemos decir que la predicción es:
print("Etiqueta predicha:",label_preds[azar_test])
print("Prenda predicha:",nombres_prendas[label_preds[azar_test]])
Etiqueta predicha: 1 Prenda predicha: Pantalón
print("MƔquina vs Humano:\n")
plt.imshow(test_images[azar_test,:,:,0],cmap='binary')
#plt.axis('off')
plt.title('Humano: ' + nombres_prendas[test_labels[azar_test]],fontsize=14)
plt.xlabel("MƔquina: "+ nombres_prendas[label_preds[azar_test]],fontsize=14)
plt.xticks([], [])
plt.yticks([], [])
plt.show()
MƔquina vs Humano:
bad_pred=[]
for i in range (len(label_preds)):
if label_preds[i]!=test_labels[i]:
bad_pred.append(i)
bad_pred=np.array(bad_pred)
print(bad_pred)
print("\nCuƔntas:",bad_pred.shape[0])
[ 23 25 42 49 57 67 68 98 147 150 244 247 248 312 316 324 378 379 381 382 389 395 441 444 455 457 460 468 474 476 491 510 525 526 572 585 607 628 639 669 670 674 688 706 711 713 724 732 738 753 760 787 851 877 881 890 894 905 909 910 925 930 935 938 956 960 965 966 976 977 979 985 997 1000 1004 1005 1025 1029 1101 1104 1107 1111 1125 1139 1140 1142 1160 1162 1165 1174 1192 1194 1197 1210 1223 1224 1231 1234 1236 1280 1286 1293 1300 1305 1312 1326 1329 1335 1336 1342 1374 1385 1388 1399 1408 1425 1450 1462 1469 1471 1496 1501 1509 1522 1528 1533 1572 1585 1602 1617 1620 1622 1626 1632 1642 1643 1650 1665 1679 1684 1712 1739 1743 1744 1746 1777 1778 1810 1826 1836 1852 1856 1861 1867 1879 1900 1922 1942 1943 1953 1964 1968 1980 2001 2006 2022 2037 2062 2067 2069 2071 2082 2097 2104 2106 2110 2144 2162 2189 2191 2195 2236 2239 2245 2252 2256 2278 2281 2290 2302 2309 2311 2318 2319 2326 2343 2351 2352 2367 2397 2425 2431 2435 2455 2457 2464 2469 2485 2487 2506 2507 2509 2527 2540 2548 2551 2571 2575 2580 2588 2599 2603 2619 2628 2629 2652 2653 2661 2670 2678 2681 2684 2689 2701 2717 2721 2732 2737 2741 2746 2760 2764 2779 2787 2814 2817 2839 2840 2842 2843 2856 2897 2898 2900 2905 2909 2914 2918 2919 2920 2934 2942 2951 2953 2965 2967 2973 2979 2985 2986 2991 2997 3001 3008 3015 3019 3038 3058 3082 3084 3101 3103 3116 3123 3132 3174 3181 3188 3198 3203 3205 3209 3220 3229 3232 3240 3241 3244 3258 3262 3282 3284 3304 3313 3322 3323 3338 3342 3370 3386 3401 3436 3439 3451 3458 3466 3468 3484 3488 3489 3491 3496 3497 3499 3507 3531 3532 3535 3540 3552 3553 3554 3572 3585 3588 3609 3613 3625 3626 3639 3640 3643 3649 3669 3671 3673 3681 3706 3730 3731 3741 3760 3765 3772 3787 3800 3804 3805 3809 3816 3829 3830 3842 3861 3864 3865 3871 3880 3881 3909 3914 3937 3938 3940 3941 3953 3954 3974 3999 4025 4041 4056 4061 4065 4067 4071 4079 4082 4084 4102 4106 4108 4109 4121 4127 4140 4142 4143 4148 4153 4159 4166 4192 4193 4224 4231 4233 4245 4251 4271 4272 4280 4299 4307 4317 4333 4337 4404 4405 4411 4416 4422 4433 4460 4462 4471 4526 4568 4569 4608 4639 4664 4668 4672 4692 4693 4705 4711 4724 4727 4742 4746 4751 4764 4782 4784 4803 4817 4823 4828 4829 4836 4850 4852 4880 4886 4896 4917 4922 4924 4934 4941 4995 5006 5009 5014 5032 5041 5052 5066 5069 5070 5077 5101 5108 5123 5129 5148 5155 5167 5173 5178 5184 5186 5197 5210 5228 5231 5248 5249 5255 5259 5260 5285 5297 5316 5334 5336 5338 5375 5381 5410 5415 5424 5452 5464 5468 5473 5497 5510 5511 5512 5520 5522 5530 5533 5566 5569 5576 5587 5589 5594 5601 5610 5623 5648 5654 5655 5661 5672 5674 5679 5689 5695 5701 5713 5718 5719 5757 5777 5806 5820 5826 5849 5899 5927 5938 5946 5966 5971 5987 6008 6012 6024 6037 6061 6065 6077 6086 6094 6096 6103 6127 6129 6147 6159 6160 6162 6168 6169 6175 6201 6205 6207 6211 6225 6230 6231 6254 6258 6280 6293 6331 6335 6344 6356 6363 6365 6395 6405 6407 6418 6433 6437 6441 6444 6453 6463 6464 6472 6474 6514 6539 6564 6566 6575 6593 6596 6625 6626 6629 6654 6655 6665 6676 6679 6688 6689 6700 6710 6721 6727 6733 6737 6751 6752 6762 6774 6797 6799 6801 6809 6822 6826 6844 6855 6861 6866 6868 6874 6899 6908 6926 6928 6940 6958 6984 7013 7024 7026 7028 7030 7040 7047 7049 7068 7073 7103 7109 7125 7130 7134 7138 7165 7167 7182 7188 7189 7190 7195 7228 7233 7249 7258 7265 7278 7307 7314 7315 7332 7343 7349 7369 7376 7393 7405 7416 7424 7442 7472 7476 7518 7526 7555 7584 7596 7613 7635 7654 7660 7679 7683 7714 7755 7761 7769 7778 7779 7800 7818 7847 7868 7876 7899 7905 7906 7914 7924 7936 7941 7945 7948 7965 7974 7976 7981 7983 7986 7998 8007 8031 8051 8054 8059 8069 8079 8085 8121 8154 8156 8205 8217 8226 8259 8260 8268 8283 8292 8296 8324 8348 8373 8374 8375 8406 8415 8425 8457 8463 8525 8532 8538 8559 8568 8569 8592 8598 8611 8617 8621 8633 8640 8645 8646 8658 8664 8669 8688 8693 8705 8706 8714 8716 8717 8725 8728 8745 8757 8763 8764 8804 8818 8826 8832 8834 8877 8879 8888 8892 8914 8919 8933 8939 8940 8949 8952 8958 9017 9032 9061 9062 9074 9086 9087 9094 9095 9100 9117 9131 9133 9149 9152 9154 9157 9165 9183 9197 9198 9210 9211 9212 9218 9235 9237 9238 9244 9247 9251 9260 9263 9291 9306 9313 9320 9325 9334 9342 9344 9347 9349 9355 9375 9398 9402 9405 9441 9445 9485 9502 9524 9531 9537 9567 9573 9577 9580 9597 9601 9645 9662 9687 9690 9692 9701 9705 9719 9743 9748 9791 9795 9835 9856 9857 9867 9876 9880 9897 9917 9919 9945 9947 9951 9953 9955 9961 9963 9972 9977 9981 9989 9991] CuƔntas: 901
azar_test= np.random.randint(len(bad_pred))
print("Mala Predicción:\n")
plt.title('Humano: ' +nombres_prendas[test_labels[bad_pred[azar_test]]],fontsize=16)
plt.imshow(test_images[bad_pred[azar_test],:,:,0],cmap='gray')
plt.xlabel("MƔquina: "+nombres_prendas[np.argmax(preds[bad_pred[azar_test]])],fontsize=14)
plt.show()
Mala Predicción:
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.metrics import plot_confusion_matrix
print('Confusion Matrix:\n')
print(confusion_matrix(test_labels, label_preds),'\n')
print(classification_report(test_labels, label_preds))
Confusion Matrix:
[[867 0 24 15 3 2 82 1 6 0]
[ 1 978 0 14 3 0 2 0 2 0]
[ 13 0 883 9 39 0 56 0 0 0]
[ 11 2 9 933 25 0 19 0 1 0]
[ 1 0 42 23 874 0 58 0 2 0]
[ 0 0 0 0 0 977 0 16 0 7]
[105 1 64 21 47 0 753 0 9 0]
[ 0 0 0 0 0 6 0 974 0 20]
[ 3 0 3 5 1 0 3 3 981 1]
[ 0 0 0 0 0 3 0 31 1 965]]
precision recall f1-score support
0 0.87 0.87 0.87 1000
1 1.00 0.98 0.99 1000
2 0.86 0.88 0.87 1000
3 0.91 0.93 0.92 1000
4 0.88 0.87 0.88 1000
5 0.99 0.98 0.98 1000
6 0.77 0.75 0.76 1000
7 0.95 0.97 0.96 1000
8 0.98 0.98 0.98 1000
9 0.97 0.96 0.97 1000
accuracy 0.92 10000
macro avg 0.92 0.92 0.92 10000
weighted avg 0.92 0.92 0.92 10000
print(nombres_prendas)
['Camiseta/top', 'Pantalón', 'Jersey', 'Vestido', 'Abrigo', 'Sandalia', 'Camisa', 'Tenis', 'Bolso', 'Botines']
f, axarr = plt.subplots(3,5,figsize=(18,12))
FIRST_IMAGE=np.random.randint(len(test_images))
SECOND_IMAGE=np.random.randint(len(test_images))
THIRD_IMAGE=np.random.randint(len(test_images))
CONVOLUTION_NUMBER=1
from tensorflow.keras import models
layer_outputs = [layer.output for layer in model.layers]
activation_model = tf.keras.models.Model(inputs = model.input, outputs = layer_outputs)
#Originals
axarr[0,0].imshow(test_images[FIRST_IMAGE].reshape(28,28),cmap='inferno')
axarr[1,0].imshow(test_images[SECOND_IMAGE].reshape(28,28),cmap='inferno')
axarr[2,0].imshow(test_images[THIRD_IMAGE].reshape(28,28),cmap='inferno')
# Convoluciones
for x in range(0,4):
# Primera Imagen
f1 = activation_model.predict(test_images[FIRST_IMAGE].reshape(1, 28, 28, 1))[x]
axarr[0,x+1].imshow(f1[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
axarr[0,x+1].grid(False)
# Segunda Imagen
f2 = activation_model.predict(test_images[SECOND_IMAGE].reshape(1, 28, 28, 1))[x]
axarr[1,x+1].imshow(f2[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
axarr[1,x+1].grid(False)
# Tercera Imagen
f3 = activation_model.predict(test_images[THIRD_IMAGE].reshape(1, 28, 28, 1))[x]
axarr[2,x+1].imshow(f3[0, : , :, CONVOLUTION_NUMBER], cmap='inferno')
axarr[2,x+1].grid(False)
Hay un conjunto muy famoso en la historia de la visión por computador y los ciber ataques:
"Originalmente, esto fue un desafĆo en la construcción de un clasificador dirigido a los mejores profesionales de aprendizaje automĆ”tico e inteligencia artificial del mundo, pero la tecnologĆa ha avanzado tan rĆ”pido que verĆ” cómo puede hacerlo en solo unos minutos con una simple programación de red neuronal convolucional." -Lawrence Moroney.
Cabe resaltar lo siguiente:
Los conjuntos de juguete de MNIST/Fashion contenĆan imĆ”genes del mismo tamaƱo y estaban a escala de grises.
Esto se aleja un poco de la vida real, asĆ que ahora enfrentaremos un problema mĆ”s difĆcil.
Un problema donde las imƔgenes vengan en todos los tamaƱos y en todos los colores :)
AsĆ que, como primera instancia, tendremos que hacer un pre-procesamiento de los datos.
Por ejemplo, colocaremos todas las imƔgenes del mismo tamaƱo (escalamiento).
Seguiremos los siguientes pasos:
ADVERTENCIA: Este ejercicio puede ser muy pesado para su computador personal. Considere usar Colaboratory
La siguiente prƔctica la haremos en Colaboratory.
Si desea hacerlo de manera local, le recomendamos usar las rutas de ficheros apropiadas para su sistema operativo.
Para este ejemplo, se usaraƔ una base filtrada de 2000 imƔgenes.
!wget --no-check-certificate \
https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip \
-O /tmp/cats_and_dogs_filtered.zip
--2021-11-12 11:38:52-- https://storage.googleapis.com/mledu-datasets/cats_and_dogs_filtered.zip Resolving storage.googleapis.com (storage.googleapis.com)... 142.250.78.176, 172.217.28.112, 172.217.30.208, ... Connecting to storage.googleapis.com (storage.googleapis.com)|142.250.78.176|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 68606236 (65M) [application/zip] Saving to: ā/tmp/cats_and_dogs_filtered.zipā /tmp/cats_and_dogs_ 100%[===================>] 65.43M 24.0MB/s in 2.7s 2021-11-12 11:38:55 (24.0 MB/s) - ā/tmp/cats_and_dogs_filtered.zipā saved [68606236/68606236]
import os
import zipfile
local_zip = '/tmp/cats_and_dogs_filtered.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('/tmp')
zip_ref.close()
base_dir = '/tmp/cats_and_dogs_filtered'
train_dir = os.path.join(base_dir, 'train')
validation_dir = os.path.join(base_dir, 'validation')
# Directory with our training cat/dog pictures
train_cats_dir = os.path.join(train_dir, 'cats')
train_dogs_dir = os.path.join(train_dir, 'dogs')
# Directory with our validation cat/dog pictures
validation_cats_dir = os.path.join(validation_dir, 'cats')
validation_dogs_dir = os.path.join(validation_dir, 'dogs')
train_cat_fnames = os.listdir( train_cats_dir )
train_dog_fnames = os.listdir( train_dogs_dir )
print(train_cat_fnames[:10])
print(train_dog_fnames[:10])
['cat.289.jpg', 'cat.428.jpg', 'cat.724.jpg', 'cat.185.jpg', 'cat.507.jpg', 'cat.950.jpg', 'cat.61.jpg', 'cat.202.jpg', 'cat.875.jpg', 'cat.521.jpg'] ['dog.525.jpg', 'dog.985.jpg', 'dog.176.jpg', 'dog.467.jpg', 'dog.608.jpg', 'dog.53.jpg', 'dog.532.jpg', 'dog.338.jpg', 'dog.837.jpg', 'dog.201.jpg']
print('total training cat images :', len(os.listdir(train_cats_dir)))
print('total training dog images :', len(os.listdir(train_dogs_dir)),'\n')
print('total validation cat images :', len(os.listdir(validation_cats_dir)))
print('total validation dog images :', len(os.listdir(validation_dogs_dir)))
total training cat images : 1000 total training dog images : 1000 total validation cat images : 500 total validation dog images : 500
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
# Malla de imagenes 4x4
nrows = 4
ncols = 4
# Indice aleatorio para iterar sobre las imagenes
pic_index = np.random.randint(len(os.listdir(train_cats_dir))-8)
# Set up matplotlib fig, and size it to fit 4x4 pics
fig = plt.gcf()
fig.set_size_inches(ncols*4, nrows*4)
# Tomar hilera de 8 desde Ćndice elegido
pic_index+=8
next_cat_pix = [os.path.join(train_cats_dir, fname)
for fname in train_cat_fnames[ pic_index-8:pic_index]
]
next_dog_pix = [os.path.join(train_dogs_dir, fname)
for fname in train_dog_fnames[ pic_index-8:pic_index]
]
for i, img_path in enumerate(next_cat_pix+next_dog_pix):
# Set up subplot; subplot indices start at 1
sp = plt.subplot(nrows, ncols, i + 1)
sp.axis('Off') # Don't show axes (or gridlines)
img = mpimg.imread(img_path)
plt.imshow(img)
plt.show()
model = tf.keras.models.Sequential([
# Note the input shape is the desired size of the image 150x150 with 3 bytes color
tf.keras.layers.Conv2D(8, (3,3), activation='relu', input_shape=(150, 150, 3)),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Dropout(0.4),
tf.keras.layers.Conv2D(16, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Dropout(0.4),
tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
tf.keras.layers.Dropout(0.4),
# Flatten the results to feed into a DNN
tf.keras.layers.Flatten(),
# 512 neuron hidden layer
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dropout(0.4),
# Only 1 output neuron. It will contain a value from 0-1 where 0 for 1 class ('cats') and 1 for the other ('dogs')
tf.keras.layers.Dense(1, activation='sigmoid')
])
Veamos un resumen de la red para ver el número de parÔmetros y estructura.
model.summary()
Model: "sequential_1"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_3 (Conv2D) (None, 148, 148, 8) 224
max_pooling2d_3 (MaxPooling (None, 74, 74, 8) 0
2D)
dropout (Dropout) (None, 74, 74, 8) 0
conv2d_4 (Conv2D) (None, 72, 72, 16) 1168
max_pooling2d_4 (MaxPooling (None, 36, 36, 16) 0
2D)
dropout_1 (Dropout) (None, 36, 36, 16) 0
conv2d_5 (Conv2D) (None, 34, 34, 32) 4640
max_pooling2d_5 (MaxPooling (None, 17, 17, 32) 0
2D)
dropout_2 (Dropout) (None, 17, 17, 32) 0
flatten_1 (Flatten) (None, 9248) 0
dense_2 (Dense) (None, 64) 591936
dropout_3 (Dropout) (None, 64) 0
dense_3 (Dense) (None, 1) 65
=================================================================
Total params: 598,033
Trainable params: 598,033
Non-trainable params: 0
_________________________________________________________________
from tensorflow.keras.optimizers import Adam
model.compile(optimizer=Adam(),
loss='binary_crossentropy',
metrics = ['accuracy'])
En este punto observaremos algo nuevo.
Como tenemos muchos datos, y serĆa muy pesado para el computador tenerlos en memoria, generaremos un apuntador a los directorios que contienen las imĆ”genes e iremos leyendolas a medida que se va entrenando la red.
Estos apuntadores se conocen como ImageDataGenerator.
Son herramientas muy útiles, porque ademÔs permiten aumentar el número de datos de manera artificial y por ejemplo, escalar los datos a un mismo tamaño.
Los invitamos a revisar sus parƔmetros opcionales, se sorprenderƔn.
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# Normalizar Datos
train_datagen = ImageDataGenerator(rescale = 1.0/255.)
test_datagen = ImageDataGenerator(rescale = 1.0/255.)
# --------------------
# Flujo de imagenes de entrenamiento en grupos de 20, escalando a 150x150 usando train_datagen generator
# --------------------
train_generator = train_datagen.flow_from_directory(train_dir,
batch_size=20,
class_mode='binary',
target_size=(150, 150))
# --------------------
# Flujo de imagenes de validación en grupos de 20, escalando a 150x150 usando test_datagen generator
# --------------------
validation_generator = test_datagen.flow_from_directory(validation_dir,
batch_size=20,
class_mode = 'binary',
target_size = (150, 150))
Found 2000 images belonging to 2 classes. Found 1000 images belonging to 2 classes.
Para mĆ”s opciones del generador, puedes ir aquĆ
history = model.fit(train_generator,
validation_data=validation_generator,
steps_per_epoch=100,
epochs=50,
validation_steps=50,
verbose=1)
Epoch 1/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1895 - accuracy: 0.9200 - val_loss: 0.8626 - val_accuracy: 0.7060 Epoch 2/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1674 - accuracy: 0.9215 - val_loss: 0.9610 - val_accuracy: 0.7120 Epoch 3/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1586 - accuracy: 0.9280 - val_loss: 0.8823 - val_accuracy: 0.7170 Epoch 4/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1466 - accuracy: 0.9300 - val_loss: 0.9580 - val_accuracy: 0.7130 Epoch 5/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1442 - accuracy: 0.9415 - val_loss: 0.9743 - val_accuracy: 0.6970 Epoch 6/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1583 - accuracy: 0.9420 - val_loss: 0.8902 - val_accuracy: 0.7060 Epoch 7/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1583 - accuracy: 0.9365 - val_loss: 0.9257 - val_accuracy: 0.7200 Epoch 8/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1453 - accuracy: 0.9355 - val_loss: 0.9943 - val_accuracy: 0.7040 Epoch 9/50 100/100 [==============================] - 5s 50ms/step - loss: 0.1711 - accuracy: 0.9295 - val_loss: 0.9187 - val_accuracy: 0.7020 Epoch 10/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1438 - accuracy: 0.9435 - val_loss: 0.9834 - val_accuracy: 0.7240 Epoch 11/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1449 - accuracy: 0.9420 - val_loss: 0.9258 - val_accuracy: 0.7120 Epoch 12/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1303 - accuracy: 0.9420 - val_loss: 0.9820 - val_accuracy: 0.7180 Epoch 13/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1508 - accuracy: 0.9425 - val_loss: 0.9774 - val_accuracy: 0.6830 Epoch 14/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1333 - accuracy: 0.9400 - val_loss: 0.9077 - val_accuracy: 0.7240 Epoch 15/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1292 - accuracy: 0.9425 - val_loss: 0.9184 - val_accuracy: 0.7040 Epoch 16/50 100/100 [==============================] - 5s 51ms/step - loss: 0.1568 - accuracy: 0.9285 - val_loss: 0.8712 - val_accuracy: 0.7250 Epoch 17/50 100/100 [==============================] - 5s 54ms/step - loss: 0.1538 - accuracy: 0.9335 - val_loss: 0.9704 - val_accuracy: 0.7230 Epoch 18/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1363 - accuracy: 0.9475 - val_loss: 1.0407 - val_accuracy: 0.6990 Epoch 19/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1270 - accuracy: 0.9495 - val_loss: 0.8955 - val_accuracy: 0.7240 Epoch 20/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1194 - accuracy: 0.9510 - val_loss: 1.0690 - val_accuracy: 0.7210 Epoch 21/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1229 - accuracy: 0.9495 - val_loss: 0.9434 - val_accuracy: 0.7280 Epoch 22/50 100/100 [==============================] - 5s 51ms/step - loss: 0.1253 - accuracy: 0.9520 - val_loss: 0.9147 - val_accuracy: 0.7330 Epoch 23/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1178 - accuracy: 0.9490 - val_loss: 0.9697 - val_accuracy: 0.7210 Epoch 24/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1227 - accuracy: 0.9490 - val_loss: 0.9946 - val_accuracy: 0.7110 Epoch 25/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1291 - accuracy: 0.9470 - val_loss: 0.9687 - val_accuracy: 0.7160 Epoch 26/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1169 - accuracy: 0.9505 - val_loss: 0.9715 - val_accuracy: 0.7330 Epoch 27/50 100/100 [==============================] - 5s 51ms/step - loss: 0.1209 - accuracy: 0.9490 - val_loss: 1.0349 - val_accuracy: 0.7280 Epoch 28/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1162 - accuracy: 0.9545 - val_loss: 0.9865 - val_accuracy: 0.7110 Epoch 29/50 100/100 [==============================] - 5s 51ms/step - loss: 0.1184 - accuracy: 0.9560 - val_loss: 1.0008 - val_accuracy: 0.7170 Epoch 30/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1207 - accuracy: 0.9490 - val_loss: 0.9439 - val_accuracy: 0.7210 Epoch 31/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1059 - accuracy: 0.9580 - val_loss: 1.0793 - val_accuracy: 0.7080 Epoch 32/50 100/100 [==============================] - 5s 50ms/step - loss: 0.1297 - accuracy: 0.9480 - val_loss: 0.9164 - val_accuracy: 0.7020 Epoch 33/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1360 - accuracy: 0.9465 - val_loss: 1.0024 - val_accuracy: 0.7180 Epoch 34/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1073 - accuracy: 0.9605 - val_loss: 1.2116 - val_accuracy: 0.7210 Epoch 35/50 100/100 [==============================] - 5s 52ms/step - loss: 0.0965 - accuracy: 0.9605 - val_loss: 1.0551 - val_accuracy: 0.7170 Epoch 36/50 100/100 [==============================] - 5s 51ms/step - loss: 0.1060 - accuracy: 0.9505 - val_loss: 1.0071 - val_accuracy: 0.7040 Epoch 37/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1137 - accuracy: 0.9510 - val_loss: 1.0026 - val_accuracy: 0.7040 Epoch 38/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1013 - accuracy: 0.9610 - val_loss: 1.1187 - val_accuracy: 0.7120 Epoch 39/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1040 - accuracy: 0.9560 - val_loss: 0.9810 - val_accuracy: 0.7180 Epoch 40/50 100/100 [==============================] - 5s 51ms/step - loss: 0.0843 - accuracy: 0.9630 - val_loss: 1.1236 - val_accuracy: 0.7150 Epoch 41/50 100/100 [==============================] - 5s 52ms/step - loss: 0.0930 - accuracy: 0.9555 - val_loss: 1.1155 - val_accuracy: 0.7260 Epoch 42/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1090 - accuracy: 0.9550 - val_loss: 1.0117 - val_accuracy: 0.7080 Epoch 43/50 100/100 [==============================] - 5s 53ms/step - loss: 0.0920 - accuracy: 0.9615 - val_loss: 1.0925 - val_accuracy: 0.7030 Epoch 44/50 100/100 [==============================] - 5s 53ms/step - loss: 0.0943 - accuracy: 0.9620 - val_loss: 1.1371 - val_accuracy: 0.6990 Epoch 45/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1127 - accuracy: 0.9520 - val_loss: 1.0863 - val_accuracy: 0.7240 Epoch 46/50 100/100 [==============================] - 5s 52ms/step - loss: 0.0976 - accuracy: 0.9570 - val_loss: 1.0503 - val_accuracy: 0.7240 Epoch 47/50 100/100 [==============================] - 5s 52ms/step - loss: 0.1073 - accuracy: 0.9530 - val_loss: 0.9961 - val_accuracy: 0.7080 Epoch 48/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1030 - accuracy: 0.9555 - val_loss: 1.1035 - val_accuracy: 0.7180 Epoch 49/50 100/100 [==============================] - 5s 53ms/step - loss: 0.0954 - accuracy: 0.9655 - val_loss: 1.1259 - val_accuracy: 0.7170 Epoch 50/50 100/100 [==============================] - 5s 53ms/step - loss: 0.1039 - accuracy: 0.9610 - val_loss: 1.0636 - val_accuracy: 0.7270
model.save('../Datos/Cats_v_Dogs.h5')
model=tf.keras.models.load_model('Cats_v_Dogs.h5')
import numpy as np
from google.colab import files
from keras.preprocessing import image
#Cargar imagen desde Colab
uploaded=files.upload()
for fn in uploaded.keys():
# Cargar imagen
path='/content/' + fn
img=image.load_img(path, target_size=(150, 150))
#Preprocesar Imagen
x=image.img_to_array(img)
x=np.expand_dims(x, axis=0)
images = np.vstack([x])
# Usar Modelo (Predecir Imagen)
classes = model.predict(images, batch_size=10)
# Mostrar resultados
print(classes)
#Clasificar
if classes[0]>0:
print(fn + " Es un Perro")
else:
print(fn + " Es un Gato")
from keras.preprocessing import image
#Cargar imagen desde un archivo local
path ='../Imagenes/'
files = ['Mila.jpg', 'Zeus.jpg']
size = 150
x = []
print('Mis gatos')
for i, file in enumerate(files):
img=image.load_img(path+file, target_size=(size, size))
sp = plt.subplot(1, 2, i + 1)
sp.axis('Off')
plt.imshow(img)
array = np.reshape(image.img_to_array(img), newshape =(1,size,size,3))
x.append(array)
images = np.vstack(x)
print('tamano del tensor', images.shape)
Mis gatos tamano del tensor (2, 150, 150, 3)
classes = model.predict(images, batch_size=2)
# Mostrar resultados
print(classes)
for i, fn in enumerate(files):
#Clasificar
if classes[i]>0:
print(fn + " Es un Perro")
else:
print(fn + " Es un Gato")
[[1.] [0.]] Mila.jpg Es un Perro Zeus.jpg Es un Gato
import numpy as np
import random
from tensorflow.keras.preprocessing.image import img_to_array, load_img
# Let's define a new Model that will take an image as input, and will output
# intermediate representations for all layers in the previous model after
# the first.
successive_outputs = [layer.output for layer in model.layers[:-3]]
#visualization_model = Model(img_input, successive_outputs)
visualization_model = tf.keras.models.Model(inputs = model.input, outputs = successive_outputs)
# Let's prepare a random input image of a cat or dog from the training set.
cat_img_files = [os.path.join(train_cats_dir, f) for f in train_cat_fnames]
dog_img_files = [os.path.join(train_dogs_dir, f) for f in train_dog_fnames]
img_path = random.choice(cat_img_files + dog_img_files)
img = load_img(img_path, target_size=(150, 150)) # this is a PIL image
x = img_to_array(img) # Numpy array with shape (150, 150, 3)
x = x.reshape((1,) + x.shape) # Numpy array with shape (1, 150, 150, 3)
# Rescale by 1/255
x /= 255.0
# Let's run our image through our network, thus obtaining all
# intermediate representations for this image.
successive_feature_maps = visualization_model.predict(x)
# These are the names of the layers, so can have them as part of our plot
layer_names = [layer.name for layer in model.layers]
# Mostrar Imagen Original
plt.figure()
plt.imshow(img)
plt.grid(False)
plt.title("Imagen Original a 150x150",fontsize=16)
# -----------------------------------------------------------------------
# Now let's display our representations
# -----------------------------------------------------------------------
for layer_name, feature_map in zip(layer_names, successive_feature_maps):
if len(feature_map.shape) == 4:
#-------------------------------------------
# Just do this for the conv / maxpool layers, not the fully-connected layers
#-------------------------------------------
n_features = feature_map.shape[-1] # number of features in the feature map
size = feature_map.shape[ 1] # feature map shape (1, size, size, n_features)
# We will tile our images in this matrix
display_grid = np.zeros((size, size * n_features))
#-------------------------------------------------
# Postprocess the feature to be visually palatable
#-------------------------------------------------
for i in range(n_features):
x = feature_map[0, :, :, i]
x -= x.mean()
x /= x.std ()
x *= 64
x += 128
x = np.clip(x, 0, 255).astype('uint8')
display_grid[:, i * size : (i + 1) * size] = x # Tile each filter into a horizontal grid
#-----------------
# Display the grid
#-----------------
scale = 35. / n_features
plt.figure(figsize=(scale * n_features, scale))
plt.title (layer_name, fontsize=18)
plt.grid (False)
plt.imshow(display_grid, aspect='auto', cmap='binary')
plt.show()
/tmp/ipykernel_51274/3497460116.py:60: RuntimeWarning: invalid value encountered in true_divide x /= x.std ()
#-----------------------------------------------------------
# Retrieve a list of list results on training and test data
# sets for each training epoch
#-----------------------------------------------------------
acc = history.history[ 'accuracy' ]
val_acc = history.history[ 'val_accuracy' ]
loss = history.history[ 'loss' ]
val_loss = history.history['val_loss' ]
epochs = range(len(acc)) # Get number of epochs
plt.figure(figsize=(20,8))
#------------------------------------------------
# Plot training and validation accuracy per epoch
#------------------------------------------------
plt.subplot(121)
plt.plot ( epochs, acc,'r',label='Training Accuracy' )
plt.plot ( epochs, val_acc,'b',label='Testing Accuracy' )
plt.title ('Training and validation accuracy',fontsize=16)
plt.grid()
plt.legend(fontsize=16)
#------------------------------------------------
# Plot training and validation loss per epoch
#------------------------------------------------
plt.subplot(122)
plt.plot ( epochs, loss,'r',label='Training Loss' )
plt.plot ( epochs, val_loss,'b',label='Testing Loss' )
plt.title ('Training and validation loss',fontsize=16)
plt.grid()
plt.legend(fontsize=16)
plt.show()
import os, signal
os.kill(os.getpid(), signal.SIGKILL)
Podremos encontrar un poco de historia sobre este dataset aquĆ.
!wget --no-check-certificate \
https://storage.googleapis.com/laurencemoroney-blog.appspot.com/horse-or-human.zip \
-O /tmp/horse-or-human.zip
--2021-11-12 14:43:24-- https://storage.googleapis.com/laurencemoroney-blog.appspot.com/horse-or-human.zip Resolving storage.googleapis.com (storage.googleapis.com)... 172.217.172.16, 172.217.30.208, 172.217.28.112, ... Connecting to storage.googleapis.com (storage.googleapis.com)|172.217.172.16|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 149574867 (143M) [application/zip] Saving to: ā/tmp/horse-or-human.zipā /tmp/horse-or-human 100%[===================>] 142.65M 27.3MB/s in 5.5s 2021-11-12 14:43:30 (25.7 MB/s) - ā/tmp/horse-or-human.zipā saved [149574867/149574867]
!wget --no-check-certificate \
https://storage.googleapis.com/laurencemoroney-blog.appspot.com/validation-horse-or-human.zip \
-O /tmp/validation-horse-or-human.zip
--2021-11-12 14:43:43-- https://storage.googleapis.com/laurencemoroney-blog.appspot.com/validation-horse-or-human.zip Resolving storage.googleapis.com (storage.googleapis.com)... 172.217.172.16, 172.217.30.208, 172.217.28.112, ... Connecting to storage.googleapis.com (storage.googleapis.com)|172.217.172.16|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 11480187 (11M) [application/zip] Saving to: ā/tmp/validation-horse-or-human.zipā /tmp/validation-hor 100%[===================>] 10.95M 15.3MB/s in 0.7s 2021-11-12 14:43:44 (15.3 MB/s) - ā/tmp/validation-horse-or-human.zipā saved [11480187/11480187]
import os
import zipfile
local_zip = '/tmp/horse-or-human.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('/tmp/horse-or-human')
local_zip = '/tmp/validation-horse-or-human.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('/tmp/validation-horse-or-human')
zip_ref.close()
# Directory with our training horse pictures
train_horse_dir = os.path.join('/tmp/horse-or-human/horses')
# Directory with our training human pictures
train_human_dir = os.path.join('/tmp/horse-or-human/humans')
# Directory with our training horse pictures
validation_horse_dir = os.path.join('/tmp/validation-horse-or-human/horses')
# Directory with our training human pictures
validation_human_dir = os.path.join('/tmp/validation-horse-or-human/humans')
train_horse_names = os.listdir(train_horse_dir)
print(train_horse_names[:10])
train_human_names = os.listdir(train_human_dir)
print(train_human_names[:10])
validation_horse_hames = os.listdir(validation_horse_dir)
print(validation_horse_hames[:10])
validation_human_names = os.listdir(validation_human_dir)
print(validation_human_names[:10])
['horse48-6.png', 'horse34-9.png', 'horse13-7.png', 'horse09-8.png', 'horse35-8.png', 'horse28-8.png', 'horse16-0.png', 'horse30-0.png', 'horse08-5.png', 'horse40-0.png'] ['human04-19.png', 'human12-19.png', 'human02-03.png', 'human17-17.png', 'human13-10.png', 'human12-28.png', 'human02-01.png', 'human11-03.png', 'human17-24.png', 'human07-06.png'] ['horse2-294.png', 'horse3-217.png', 'horse5-103.png', 'horse5-002.png', 'horse5-123.png', 'horse4-468.png', 'horse5-303.png', 'horse5-565.png', 'horse3-397.png', 'horse1-105.png'] ['valhuman02-06.png', 'valhuman01-01.png', 'valhuman02-22.png', 'valhuman01-21.png', 'valhuman01-00.png', 'valhuman05-10.png', 'valhuman03-23.png', 'valhuman01-07.png', 'valhuman01-04.png', 'valhuman05-16.png']
print('total training horse images:', len(os.listdir(train_horse_dir)))
print('total training human images:', len(os.listdir(train_human_dir)))
print('total validation horse images:', len(os.listdir(validation_horse_dir)))
print('total validation human images:', len(os.listdir(validation_human_dir)))
total training horse images: 500 total training human images: 527 total validation horse images: 128 total validation human images: 128
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
# Parameters for our graph; we'll output images in a 4x4 configuration
nrows = 4
ncols = 4
# Index for iterating over images
pic_index = 0
# Set up matplotlib fig, and size it to fit 4x4 pics
fig = plt.gcf()
fig.set_size_inches(ncols * 4, nrows * 4)
pic_index += 8
next_horse_pix = [os.path.join(train_horse_dir, fname)
for fname in train_horse_names[pic_index-8:pic_index]]
next_human_pix = [os.path.join(train_human_dir, fname)
for fname in train_human_names[pic_index-8:pic_index]]
for i, img_path in enumerate(next_horse_pix+next_human_pix):
# Set up subplot; subplot indices start at 1
sp = plt.subplot(nrows, ncols, i + 1)
sp.axis('Off') # Don't show axes (or gridlines)
img = mpimg.imread(img_path)
plt.imshow(img)
plt.show()
model = tf.keras.models.Sequential([
# Note the input shape is the desired size of the image 300x300 with 3 bytes color
# This is the first convolution
tf.keras.layers.Conv2D(16, (3,3), activation='relu', input_shape=(300, 300, 3)),
tf.keras.layers.MaxPooling2D(2, 2),
# The second convolution
tf.keras.layers.Conv2D(32, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The third convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The fourth convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The fifth convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# Flatten the results to feed into a DNN
tf.keras.layers.Flatten(),
# 512 neuron hidden layer
tf.keras.layers.Dense(512, activation='relu'),
# Only 1 output neuron. It will contain a value from 0-1 where 0 for 1 class ('horses') and 1 for the other ('humans')
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.summary()
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d_6 (Conv2D) (None, 298, 298, 16) 448
max_pooling2d_6 (MaxPooling (None, 149, 149, 16) 0
2D)
conv2d_7 (Conv2D) (None, 147, 147, 32) 4640
max_pooling2d_7 (MaxPooling (None, 73, 73, 32) 0
2D)
conv2d_8 (Conv2D) (None, 71, 71, 64) 18496
max_pooling2d_8 (MaxPooling (None, 35, 35, 64) 0
2D)
conv2d_9 (Conv2D) (None, 33, 33, 64) 36928
max_pooling2d_9 (MaxPooling (None, 16, 16, 64) 0
2D)
conv2d_10 (Conv2D) (None, 14, 14, 64) 36928
max_pooling2d_10 (MaxPoolin (None, 7, 7, 64) 0
g2D)
flatten_2 (Flatten) (None, 3136) 0
dense_4 (Dense) (None, 512) 1606144
dense_5 (Dense) (None, 1) 513
=================================================================
Total params: 1,704,097
Trainable params: 1,704,097
Non-trainable params: 0
_________________________________________________________________
from tensorflow.keras.optimizers import RMSprop
model.compile(loss='binary_crossentropy',
optimizer=Adam(),
metrics=['accuracy'])
from tensorflow.keras.preprocessing.image import ImageDataGenerator
# All images will be rescaled by 1./255
train_datagen = ImageDataGenerator(rescale=1/255)
validation_datagen = ImageDataGenerator(rescale=1/255)
# Flow training images in batches of 128 using train_datagen generator
train_generator = train_datagen.flow_from_directory(
'/tmp/horse-or-human/', # This is the source directory for training images
target_size=(300, 300), # All images will be resized to 300x300
batch_size=128,
# Since we use binary_crossentropy loss, we need binary labels
class_mode='binary')
# Flow training images in batches of 128 using train_datagen generator
validation_generator = validation_datagen.flow_from_directory(
'/tmp/validation-horse-or-human/', # This is the source directory for training images
target_size=(300, 300), # All images will be resized to 300x300
batch_size=32,
# Since we use binary_crossentropy loss, we need binary labels
class_mode='binary')
Found 1027 images belonging to 2 classes. Found 256 images belonging to 2 classes.
history = model.fit(
train_generator,
steps_per_epoch=8,
epochs=15,
verbose=1,
validation_data = validation_generator,
validation_steps=8)
Epoch 1/15 8/8 [==============================] - 4s 503ms/step - loss: 0.0041 - accuracy: 1.0000 - val_loss: 3.3293 - val_accuracy: 0.8203 Epoch 2/15 8/8 [==============================] - 4s 488ms/step - loss: 0.0067 - accuracy: 0.9978 - val_loss: 3.7326 - val_accuracy: 0.7656 Epoch 3/15 8/8 [==============================] - 4s 483ms/step - loss: 0.0052 - accuracy: 0.9978 - val_loss: 1.7279 - val_accuracy: 0.8672 Epoch 4/15 8/8 [==============================] - 4s 491ms/step - loss: 0.0072 - accuracy: 0.9978 - val_loss: 4.0664 - val_accuracy: 0.7461 Epoch 5/15 8/8 [==============================] - 4s 551ms/step - loss: 0.0019 - accuracy: 1.0000 - val_loss: 4.3019 - val_accuracy: 0.7773 Epoch 6/15 8/8 [==============================] - 4s 489ms/step - loss: 0.0010 - accuracy: 1.0000 - val_loss: 3.6802 - val_accuracy: 0.8125 Epoch 7/15 8/8 [==============================] - 4s 542ms/step - loss: 6.6223e-04 - accuracy: 1.0000 - val_loss: 3.6925 - val_accuracy: 0.8203 Epoch 8/15 8/8 [==============================] - 4s 484ms/step - loss: 3.0292e-04 - accuracy: 1.0000 - val_loss: 3.7078 - val_accuracy: 0.8242 Epoch 9/15 8/8 [==============================] - 4s 501ms/step - loss: 2.4854e-04 - accuracy: 1.0000 - val_loss: 3.7560 - val_accuracy: 0.8242 Epoch 10/15 8/8 [==============================] - 4s 498ms/step - loss: 1.8106e-04 - accuracy: 1.0000 - val_loss: 3.8736 - val_accuracy: 0.8203 Epoch 11/15 8/8 [==============================] - 4s 483ms/step - loss: 1.5875e-04 - accuracy: 1.0000 - val_loss: 3.8773 - val_accuracy: 0.8203 Epoch 12/15 8/8 [==============================] - 4s 488ms/step - loss: 1.3453e-04 - accuracy: 1.0000 - val_loss: 3.8154 - val_accuracy: 0.8320 Epoch 13/15 8/8 [==============================] - 4s 484ms/step - loss: 1.1901e-04 - accuracy: 1.0000 - val_loss: 3.8575 - val_accuracy: 0.8281 Epoch 14/15 8/8 [==============================] - 4s 491ms/step - loss: 9.2547e-05 - accuracy: 1.0000 - val_loss: 3.8898 - val_accuracy: 0.8281 Epoch 15/15 8/8 [==============================] - 4s 480ms/step - loss: 9.5020e-05 - accuracy: 1.0000 - val_loss: 3.9102 - val_accuracy: 0.8320
model.save('../Datos/Horses_or_Humans.h5')
model=tf.keras.models.load_model('../Datos/Horses_or_Humans.h5')
import numpy as np
from google.colab import files
from keras.preprocessing import image
uploaded = files.upload()
for fn in uploaded.keys():
# predicting images
path = '/content/' + fn
img = image.load_img(path, target_size=(300, 300))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
images = np.vstack([x])
classes = model.predict(images, batch_size=10)
print(classes[0])
if classes[0]>0:
print(fn + " is a human")
else:
print(fn + " is a horse")
import numpy as np
import random
from tensorflow.keras.preprocessing.image import img_to_array, load_img
# Let's define a new Model that will take an image as input, and will output
# intermediate representations for all layers in the previous model after
# the first.
successive_outputs = [layer.output for layer in model.layers[1:]]
#visualization_model = Model(img_input, successive_outputs)
visualization_model = tf.keras.models.Model(inputs = model.input, outputs = successive_outputs)
# Let's prepare a random input image from the training set.
horse_img_files = [os.path.join(train_horse_dir, f) for f in train_horse_names]
human_img_files = [os.path.join(train_human_dir, f) for f in train_human_names]
img_path = random.choice(horse_img_files + human_img_files)
img = load_img(img_path, target_size=(300, 300)) # this is a PIL image
x = img_to_array(img) # Numpy array with shape (150, 150, 3)
x = x.reshape((1,) + x.shape) # Numpy array with shape (1, 150, 150, 3)
# Rescale by 1/255
x /= 255
# Let's run our image through our network, thus obtaining all
# intermediate representations for this image.
successive_feature_maps = visualization_model.predict(x)
# These are the names of the layers, so can have them as part of our plot
layer_names = [layer.name for layer in model.layers[:-2]]
# Mostrar Imagen Original
plt.figure()
plt.imshow(img)
plt.grid(False)
plt.title("Imagen Original a 300x300",fontsize=16)
# Now let's display our representations
for layer_name, feature_map in zip(layer_names, successive_feature_maps):
if len(feature_map.shape) == 4:
# Just do this for the conv / maxpool layers, not the fully-connected layers
n_features = feature_map.shape[-1] # number of features in feature map
# The feature map has shape (1, size, size, n_features)
size = feature_map.shape[1]
# We will tile our images in this matrix
display_grid = np.zeros((size, size * n_features))
for i in range(n_features):
# Postprocess the feature to make it visually palatable
x = feature_map[0, :, :, i]
x -= x.mean()
x /= x.std()
x *= 64
x += 128
x = np.clip(x, 0, 255).astype('uint8')
# We'll tile each filter into this big horizontal grid
display_grid[:, i * size : (i + 1) * size] = x
# Display the grid
scale = 20. / n_features
plt.figure(figsize=(scale * n_features, scale))
plt.title(layer_name)
plt.grid(False)
plt.imshow(display_grid, aspect='auto', cmap='binary')
/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:49: RuntimeWarning: invalid value encountered in true_divide
import os, signal
os.kill(os.getpid(), signal.SIGKILL)
Este ejemplo es un poco mÔs complejo, pues haremos clasificación en tres clases de manos de diferentes tipos.
Las manos humanas tienen muchos rasgos distintos que hace que el proceso de clasificación no sea trivial.
!wget --no-check-certificate \
https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps.zip \
-O /tmp/rps.zip
!wget --no-check-certificate \
https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps-test-set.zip \
-O /tmp/rps-test-set.zip
--2020-10-08 19:45:43-- https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps.zip Resolving storage.googleapis.com (storage.googleapis.com)... 108.177.119.128, 108.177.126.128, 108.177.127.128, ... Connecting to storage.googleapis.com (storage.googleapis.com)|108.177.119.128|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 200682221 (191M) [application/zip] Saving to: ā/tmp/rps.zipā /tmp/rps.zip 100%[===================>] 191.38M 45.1MB/s in 4.2s 2020-10-08 19:45:47 (45.1 MB/s) - ā/tmp/rps.zipā saved [200682221/200682221] --2020-10-08 19:45:48-- https://storage.googleapis.com/laurencemoroney-blog.appspot.com/rps-test-set.zip Resolving storage.googleapis.com (storage.googleapis.com)... 108.177.126.128, 108.177.127.128, 172.217.218.128, ... Connecting to storage.googleapis.com (storage.googleapis.com)|108.177.126.128|:443... connected. HTTP request sent, awaiting response... 200 OK Length: 29516758 (28M) [application/zip] Saving to: ā/tmp/rps-test-set.zipā /tmp/rps-test-set.z 100%[===================>] 28.15M 74.3MB/s in 0.4s 2020-10-08 19:45:48 (74.3 MB/s) - ā/tmp/rps-test-set.zipā saved [29516758/29516758]
import os
import zipfile
local_zip = '/tmp/rps.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('/tmp/')
zip_ref.close()
local_zip = '/tmp/rps-test-set.zip'
zip_ref = zipfile.ZipFile(local_zip, 'r')
zip_ref.extractall('/tmp/')
zip_ref.close()
rock_dir = os.path.join('/tmp/rps/rock')
paper_dir = os.path.join('/tmp/rps/paper')
scissors_dir = os.path.join('/tmp/rps/scissors')
print('total training rock images:', len(os.listdir(rock_dir)))
print('total training paper images:', len(os.listdir(paper_dir)))
print('total training scissors images:', len(os.listdir(scissors_dir)))
rock_files = os.listdir(rock_dir)
print(rock_files[:10])
paper_files = os.listdir(paper_dir)
print(paper_files[:10])
scissors_files = os.listdir(scissors_dir)
print(scissors_files[:10])
total training rock images: 840 total training paper images: 840 total training scissors images: 840 ['rock01-071.png', 'rock02-049.png', 'rock06ck02-078.png', 'rock01-012.png', 'rock01-049.png', 'rock01-092.png', 'rock01-114.png', 'rock05ck01-053.png', 'rock06ck02-021.png', 'rock02-113.png'] ['paper05-107.png', 'paper01-072.png', 'paper04-025.png', 'paper05-097.png', 'paper03-048.png', 'paper03-029.png', 'paper02-032.png', 'paper02-013.png', 'paper01-045.png', 'paper06-081.png'] ['scissors04-088.png', 'scissors01-052.png', 'scissors02-061.png', 'scissors02-080.png', 'testscissors03-031.png', 'scissors04-073.png', 'scissors02-063.png', 'scissors02-027.png', 'scissors01-017.png', 'testscissors01-117.png']
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
pic_index = 2
next_rock = [os.path.join(rock_dir, fname)
for fname in rock_files[pic_index-2:pic_index]]
next_paper = [os.path.join(paper_dir, fname)
for fname in paper_files[pic_index-2:pic_index]]
next_scissors = [os.path.join(scissors_dir, fname)
for fname in scissors_files[pic_index-2:pic_index]]
for i, img_path in enumerate(next_rock+next_paper+next_scissors):
#print(img_path)
img = mpimg.imread(img_path)
plt.imshow(img)
plt.axis('Off')
plt.show()
Una técnica natural en DL para obtener datos sintéticos que pueden ayudar a la red neuronal es mediante la técnica llamada aumentación de datos (Data augmentation)
Vemos un blog al respecto:
import tensorflow as tf
import keras_preprocessing
from keras_preprocessing import image
from keras_preprocessing.image import ImageDataGenerator
TRAINING_DIR = "/tmp/rps/"
training_datagen = ImageDataGenerator(
rescale = 1./255,
rotation_range=40,
width_shift_range=0.2,
height_shift_range=0.2,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
VALIDATION_DIR = "/tmp/rps-test-set/"
validation_datagen = ImageDataGenerator(rescale = 1./255)
train_generator = training_datagen.flow_from_directory(
TRAINING_DIR,
target_size=(150,150),
class_mode='categorical',
batch_size=126
)
validation_generator = validation_datagen.flow_from_directory(
VALIDATION_DIR,
target_size=(150,150),
class_mode='categorical',
batch_size=126
)
model = tf.keras.models.Sequential([
# Note the input shape is the desired size of the image 150x150 with 3 bytes color
# This is the first convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu', input_shape=(150, 150, 3)),
tf.keras.layers.MaxPooling2D(2, 2),
# The second convolution
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The third convolution
tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# The fourth convolution
tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D(2,2),
# Flatten the results to feed into a DNN
tf.keras.layers.Flatten(),
tf.keras.layers.Dropout(0.5),
# 512 neuron hidden layer
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dense(3, activation='softmax')
])
model.summary()
model.compile(loss = 'categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
history = model.fit(train_generator, epochs=25, steps_per_epoch=20, validation_data = validation_generator, verbose = 1, validation_steps=3)
model.save("rps.h5")
Found 2520 images belonging to 3 classes. Found 372 images belonging to 3 classes. Model: "sequential_7" _________________________________________________________________ Layer (type) Output Shape Param # ================================================================= conv2d_17 (Conv2D) (None, 148, 148, 64) 1792 _________________________________________________________________ max_pooling2d_17 (MaxPooling (None, 74, 74, 64) 0 _________________________________________________________________ conv2d_18 (Conv2D) (None, 72, 72, 64) 36928 _________________________________________________________________ max_pooling2d_18 (MaxPooling (None, 36, 36, 64) 0 _________________________________________________________________ conv2d_19 (Conv2D) (None, 34, 34, 128) 73856 _________________________________________________________________ max_pooling2d_19 (MaxPooling (None, 17, 17, 128) 0 _________________________________________________________________ conv2d_20 (Conv2D) (None, 15, 15, 128) 147584 _________________________________________________________________ max_pooling2d_20 (MaxPooling (None, 7, 7, 128) 0 _________________________________________________________________ flatten_7 (Flatten) (None, 6272) 0 _________________________________________________________________ dropout (Dropout) (None, 6272) 0 _________________________________________________________________ dense_14 (Dense) (None, 512) 3211776 _________________________________________________________________ dense_15 (Dense) (None, 3) 1539 ================================================================= Total params: 3,473,475 Trainable params: 3,473,475 Non-trainable params: 0 _________________________________________________________________ Epoch 1/25 20/20 [==============================] - 18s 913ms/step - loss: 1.7653 - accuracy: 0.3508 - val_loss: 1.1284 - val_accuracy: 0.3333 Epoch 2/25 20/20 [==============================] - 18s 885ms/step - loss: 1.0951 - accuracy: 0.3845 - val_loss: 1.0036 - val_accuracy: 0.3333 Epoch 3/25 20/20 [==============================] - 18s 885ms/step - loss: 1.1114 - accuracy: 0.3786 - val_loss: 1.0552 - val_accuracy: 0.7366 Epoch 4/25 20/20 [==============================] - 18s 884ms/step - loss: 1.0968 - accuracy: 0.4508 - val_loss: 0.8790 - val_accuracy: 0.5511 Epoch 5/25 20/20 [==============================] - 18s 895ms/step - loss: 1.1299 - accuracy: 0.5294 - val_loss: 0.9576 - val_accuracy: 0.5188 Epoch 6/25 20/20 [==============================] - 18s 885ms/step - loss: 0.8538 - accuracy: 0.6107 - val_loss: 1.1898 - val_accuracy: 0.4516 Epoch 7/25 20/20 [==============================] - 18s 884ms/step - loss: 0.8080 - accuracy: 0.6524 - val_loss: 0.3756 - val_accuracy: 0.9409 Epoch 8/25 20/20 [==============================] - 18s 889ms/step - loss: 0.7358 - accuracy: 0.6754 - val_loss: 0.2819 - val_accuracy: 0.9516 Epoch 9/25 20/20 [==============================] - 18s 892ms/step - loss: 0.5776 - accuracy: 0.7536 - val_loss: 0.2242 - val_accuracy: 0.8871 Epoch 10/25 20/20 [==============================] - 18s 885ms/step - loss: 0.5687 - accuracy: 0.7675 - val_loss: 0.6149 - val_accuracy: 0.5591 Epoch 11/25 20/20 [==============================] - 18s 883ms/step - loss: 0.4737 - accuracy: 0.8079 - val_loss: 0.4801 - val_accuracy: 0.7097 Epoch 12/25 20/20 [==============================] - 18s 882ms/step - loss: 0.2945 - accuracy: 0.8889 - val_loss: 0.5513 - val_accuracy: 0.7661 Epoch 13/25 20/20 [==============================] - 18s 888ms/step - loss: 0.3896 - accuracy: 0.8385 - val_loss: 0.1320 - val_accuracy: 0.9328 Epoch 14/25 20/20 [==============================] - 18s 887ms/step - loss: 0.2583 - accuracy: 0.9012 - val_loss: 0.0343 - val_accuracy: 0.9919 Epoch 15/25 20/20 [==============================] - 18s 882ms/step - loss: 0.2377 - accuracy: 0.9107 - val_loss: 0.0546 - val_accuracy: 0.9946 Epoch 16/25 20/20 [==============================] - 18s 889ms/step - loss: 0.1675 - accuracy: 0.9421 - val_loss: 0.1157 - val_accuracy: 0.9516 Epoch 17/25 20/20 [==============================] - 18s 889ms/step - loss: 0.2228 - accuracy: 0.9187 - val_loss: 0.0418 - val_accuracy: 0.9866 Epoch 18/25 20/20 [==============================] - 18s 894ms/step - loss: 0.1443 - accuracy: 0.9488 - val_loss: 0.0593 - val_accuracy: 0.9758 Epoch 19/25 20/20 [==============================] - 18s 882ms/step - loss: 0.2072 - accuracy: 0.9306 - val_loss: 0.0770 - val_accuracy: 0.9731 Epoch 20/25 20/20 [==============================] - 18s 884ms/step - loss: 0.1307 - accuracy: 0.9556 - val_loss: 0.1056 - val_accuracy: 0.9489 Epoch 21/25 20/20 [==============================] - 18s 888ms/step - loss: 0.2696 - accuracy: 0.9004 - val_loss: 0.0433 - val_accuracy: 0.9839 Epoch 22/25 20/20 [==============================] - 18s 888ms/step - loss: 0.1245 - accuracy: 0.9512 - val_loss: 1.1970 - val_accuracy: 0.6667 Epoch 23/25 20/20 [==============================] - 18s 885ms/step - loss: 0.2026 - accuracy: 0.9508 - val_loss: 0.1453 - val_accuracy: 0.9516 Epoch 24/25 20/20 [==============================] - 18s 883ms/step - loss: 0.1183 - accuracy: 0.9548 - val_loss: 0.0200 - val_accuracy: 1.0000 Epoch 25/25 20/20 [==============================] - 18s 883ms/step - loss: 0.0956 - accuracy: 0.9651 - val_loss: 0.0218 - val_accuracy: 0.9892
import matplotlib.pyplot as plt
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(len(acc))
plt.figure(figsize=(18,5))
#------------------------------------------------
# Plot training and validation accuracy per epoch
#------------------------------------------------
plt.subplot(121)
plt.plot ( epochs, acc,'r',label='Training Accuracy' )
plt.plot ( epochs, val_acc,'b',label='Testing Accuracy' )
plt.title ('Training and validation accuracy',fontsize=16)
plt.grid()
plt.legend(fontsize=16)
#------------------------------------------------
# Plot training and validation loss per epoch
#------------------------------------------------
plt.subplot(122)
plt.plot ( epochs, loss,'r',label='Training Loss' )
plt.plot ( epochs, val_loss,'b',label='Testing Loss' )
plt.title ('Training and validation loss',fontsize=16)
plt.grid()
plt.legend(fontsize=16)
plt.show()
model=tf.keras.models.load_model('rps.h5')
preds=model.predict(validation_generator)
preds[:5]
WARNING:tensorflow:5 out of the last 54 calls to <function Model.make_predict_function.<locals>.predict_function at 0x7f442cf9cea0> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/tutorials/customization/performance#python_or_tensor_args and https://www.tensorflow.org/api_docs/python/tf/function for more details.
array([[6.1073937e-09, 9.9999928e-01, 6.6503407e-07],
[1.4923323e-07, 9.9999988e-01, 1.0823758e-08],
[8.9176693e-09, 9.9999952e-01, 4.2809245e-07],
[9.9999690e-01, 2.6853102e-06, 3.9489521e-07],
[9.9999976e-01, 1.2737560e-07, 1.3945728e-07]], dtype=float32)
import numpy as np
from google.colab import files
from keras.preprocessing import image
uploaded = files.upload()
for fn in uploaded.keys():
# predicting images
path = fn
img = image.load_img(path, target_size=(150, 150))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
images = np.vstack([x])
classes = model.predict(images, batch_size=10)
print(fn)
print(classes)
## [paper,rock,scissors]
Saving 2020-10-08-113519.jpg to 2020-10-08-113519 (4).jpg WARNING:tensorflow:6 out of the last 57 calls to <function Model.make_predict_function.<locals>.predict_function at 0x7f442cf9cea0> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/tutorials/customization/performance#python_or_tensor_args and https://www.tensorflow.org/api_docs/python/tf/function for more details. 2020-10-08-113519.jpg [[0. 1. 0.]]
Conclusión: A jugar!